package com.ami.kvm.jviewer.hid;

import java.awt.event.KeyEvent;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;

import com.ami.kvm.jviewer.Debug;
import com.ami.kvm.jviewer.gui.LocaleStrings;

public class USBKeyProcessorEnglish implements KeyProcessor {
	protected HashMap<Integer, Integer> standardMap;
	protected HashMap<Integer, Integer> keypadMap;
	protected HashMap<Integer, Integer> leftMap;
	protected HashMap<Integer, Integer> rightMap;
	protected static byte modifiers = 0;
	protected boolean autoKeybreakModeOn = false;
	final int USB_KEYBOARD_REPORT_SIZE = 8;

	public USBKeyProcessorEnglish() {
		this.standardMap = new HashMap<Integer, Integer>();
		this.keypadMap = new HashMap<Integer, Integer>();
		this.leftMap = new HashMap<Integer, Integer>();
		this.rightMap = new HashMap<Integer, Integer>();

		this.standardMap.put(Integer.valueOf(65), Integer.valueOf(4));
		this.standardMap.put(Integer.valueOf(66), Integer.valueOf(5));
		this.standardMap.put(Integer.valueOf(67), Integer.valueOf(6));
		this.standardMap.put(Integer.valueOf(68), Integer.valueOf(7));
		this.standardMap.put(Integer.valueOf(69), Integer.valueOf(8));
		this.standardMap.put(Integer.valueOf(70), Integer.valueOf(9));
		this.standardMap.put(Integer.valueOf(71), Integer.valueOf(10));
		this.standardMap.put(Integer.valueOf(72), Integer.valueOf(11));
		this.standardMap.put(Integer.valueOf(73), Integer.valueOf(12));
		this.standardMap.put(Integer.valueOf(74), Integer.valueOf(13));
		this.standardMap.put(Integer.valueOf(75), Integer.valueOf(14));
		this.standardMap.put(Integer.valueOf(76), Integer.valueOf(15));
		this.standardMap.put(Integer.valueOf(77), Integer.valueOf(16));
		this.standardMap.put(Integer.valueOf(78), Integer.valueOf(17));
		this.standardMap.put(Integer.valueOf(79), Integer.valueOf(18));
		this.standardMap.put(Integer.valueOf(80), Integer.valueOf(19));
		this.standardMap.put(Integer.valueOf(81), Integer.valueOf(20));
		this.standardMap.put(Integer.valueOf(82), Integer.valueOf(21));
		this.standardMap.put(Integer.valueOf(83), Integer.valueOf(22));
		this.standardMap.put(Integer.valueOf(84), Integer.valueOf(23));
		this.standardMap.put(Integer.valueOf(85), Integer.valueOf(24));
		this.standardMap.put(Integer.valueOf(86), Integer.valueOf(25));
		this.standardMap.put(Integer.valueOf(87), Integer.valueOf(26));
		this.standardMap.put(Integer.valueOf(88), Integer.valueOf(27));
		this.standardMap.put(Integer.valueOf(89), Integer.valueOf(28));
		this.standardMap.put(Integer.valueOf(90), Integer.valueOf(29));
		this.standardMap.put(Integer.valueOf(49), Integer.valueOf(30));
		this.standardMap.put(Integer.valueOf(50), Integer.valueOf(31));
		this.standardMap.put(Integer.valueOf(51), Integer.valueOf(32));
		this.standardMap.put(Integer.valueOf(52), Integer.valueOf(33));
		this.standardMap.put(Integer.valueOf(53), Integer.valueOf(34));
		this.standardMap.put(Integer.valueOf(54), Integer.valueOf(35));
		this.standardMap.put(Integer.valueOf(55), Integer.valueOf(36));
		this.standardMap.put(Integer.valueOf(56), Integer.valueOf(37));
		this.standardMap.put(Integer.valueOf(57), Integer.valueOf(38));
		this.standardMap.put(Integer.valueOf(48), Integer.valueOf(39));
		this.standardMap.put(Integer.valueOf(10), Integer.valueOf(40));
		this.standardMap.put(Integer.valueOf(27), Integer.valueOf(41));
		this.standardMap.put(Integer.valueOf(8), Integer.valueOf(42));
		this.standardMap.put(Integer.valueOf(9), Integer.valueOf(43));
		this.standardMap.put(Integer.valueOf(32), Integer.valueOf(44));
		this.standardMap.put(Integer.valueOf(45), Integer.valueOf(45));
		this.standardMap.put(Integer.valueOf(61), Integer.valueOf(46));
		this.standardMap.put(Integer.valueOf(91), Integer.valueOf(47));
		this.standardMap.put(Integer.valueOf(93), Integer.valueOf(48));
		this.standardMap.put(Integer.valueOf(92), Integer.valueOf(49));

		this.standardMap.put(Integer.valueOf(59), Integer.valueOf(51));
		this.standardMap.put(Integer.valueOf(222), Integer.valueOf(52));
		this.standardMap.put(Integer.valueOf(192), Integer.valueOf(53));
		this.standardMap.put(Integer.valueOf(44), Integer.valueOf(54));
		this.standardMap.put(Integer.valueOf(46), Integer.valueOf(55));
		this.standardMap.put(Integer.valueOf(47), Integer.valueOf(56));
		this.standardMap.put(Integer.valueOf(20), Integer.valueOf(57));
		this.standardMap.put(Integer.valueOf(112), Integer.valueOf(58));
		this.standardMap.put(Integer.valueOf(113), Integer.valueOf(59));
		this.standardMap.put(Integer.valueOf(114), Integer.valueOf(60));
		this.standardMap.put(Integer.valueOf(115), Integer.valueOf(61));
		this.standardMap.put(Integer.valueOf(116), Integer.valueOf(62));
		this.standardMap.put(Integer.valueOf(117), Integer.valueOf(63));
		this.standardMap.put(Integer.valueOf(118), Integer.valueOf(64));
		this.standardMap.put(Integer.valueOf(119), Integer.valueOf(65));
		this.standardMap.put(Integer.valueOf(120), Integer.valueOf(66));
		this.standardMap.put(Integer.valueOf(121), Integer.valueOf(67));
		this.standardMap.put(Integer.valueOf(122), Integer.valueOf(68));
		this.standardMap.put(Integer.valueOf(123), Integer.valueOf(69));
		this.standardMap.put(Integer.valueOf(154), Integer.valueOf(70));
		this.standardMap.put(Integer.valueOf(145), Integer.valueOf(71));
		this.standardMap.put(Integer.valueOf(19), Integer.valueOf(72));
		this.standardMap.put(Integer.valueOf(155), Integer.valueOf(73));
		this.standardMap.put(Integer.valueOf(36), Integer.valueOf(74));
		this.standardMap.put(Integer.valueOf(33), Integer.valueOf(75));
		this.standardMap.put(Integer.valueOf(127), Integer.valueOf(76));
		this.standardMap.put(Integer.valueOf(35), Integer.valueOf(77));
		this.standardMap.put(Integer.valueOf(34), Integer.valueOf(78));
		this.standardMap.put(Integer.valueOf(39), Integer.valueOf(79));
		this.standardMap.put(Integer.valueOf(37), Integer.valueOf(80));
		this.standardMap.put(Integer.valueOf(40), Integer.valueOf(81));
		this.standardMap.put(Integer.valueOf(38), Integer.valueOf(82));
		this.standardMap.put(Integer.valueOf(109), Integer.valueOf(86));

		this.keypadMap.put(Integer.valueOf(144), Integer.valueOf(83));
		this.keypadMap.put(Integer.valueOf(111), Integer.valueOf(84));
		this.keypadMap.put(Integer.valueOf(106), Integer.valueOf(85));
		this.keypadMap.put(Integer.valueOf(109), Integer.valueOf(86));
		this.keypadMap.put(Integer.valueOf(107), Integer.valueOf(87));
		this.keypadMap.put(Integer.valueOf(10), Integer.valueOf(88));
		this.keypadMap.put(Integer.valueOf(97), Integer.valueOf(89));
		this.keypadMap.put(Integer.valueOf(35), Integer.valueOf(89));
		this.keypadMap.put(Integer.valueOf(98), Integer.valueOf(90));
		this.keypadMap.put(Integer.valueOf(40), Integer.valueOf(90));
		this.keypadMap.put(Integer.valueOf(225), Integer.valueOf(90));
		this.keypadMap.put(Integer.valueOf(99), Integer.valueOf(91));
		this.keypadMap.put(Integer.valueOf(34), Integer.valueOf(91));
		this.keypadMap.put(Integer.valueOf(100), Integer.valueOf(92));
		this.keypadMap.put(Integer.valueOf(37), Integer.valueOf(92));
		this.keypadMap.put(Integer.valueOf(226), Integer.valueOf(92));
		this.keypadMap.put(Integer.valueOf(101), Integer.valueOf(93));
		this.keypadMap.put(Integer.valueOf(65368), Integer.valueOf(93));
		this.keypadMap.put(Integer.valueOf(102), Integer.valueOf(94));
		this.keypadMap.put(Integer.valueOf(39), Integer.valueOf(94));
		this.keypadMap.put(Integer.valueOf(227), Integer.valueOf(94));
		this.keypadMap.put(Integer.valueOf(103), Integer.valueOf(95));
		this.keypadMap.put(Integer.valueOf(36), Integer.valueOf(95));
		this.keypadMap.put(Integer.valueOf(104), Integer.valueOf(96));
		this.keypadMap.put(Integer.valueOf(38), Integer.valueOf(96));
		this.keypadMap.put(Integer.valueOf(224), Integer.valueOf(96));
		this.keypadMap.put(Integer.valueOf(105), Integer.valueOf(97));
		this.keypadMap.put(Integer.valueOf(33), Integer.valueOf(97));
		this.keypadMap.put(Integer.valueOf(96), Integer.valueOf(98));
		this.keypadMap.put(Integer.valueOf(155), Integer.valueOf(98));
		this.keypadMap.put(Integer.valueOf(110), Integer.valueOf(99));
		this.keypadMap.put(Integer.valueOf(127), Integer.valueOf(76));

		this.standardMap.put(Integer.valueOf(153), Integer.valueOf(100));
		this.keypadMap.put(Integer.valueOf(61), Integer.valueOf(103));

		this.standardMap.put(Integer.valueOf(525), Integer.valueOf(101));
		this.standardMap.put(Integer.valueOf(61440), Integer.valueOf(104));
		this.standardMap.put(Integer.valueOf(61441), Integer.valueOf(105));
		this.standardMap.put(Integer.valueOf(61442), Integer.valueOf(106));
		this.standardMap.put(Integer.valueOf(61443), Integer.valueOf(107));
		this.standardMap.put(Integer.valueOf(61444), Integer.valueOf(108));
		this.standardMap.put(Integer.valueOf(61445), Integer.valueOf(109));
		this.standardMap.put(Integer.valueOf(61446), Integer.valueOf(110));
		this.standardMap.put(Integer.valueOf(61447), Integer.valueOf(111));
		this.standardMap.put(Integer.valueOf(61448), Integer.valueOf(112));
		this.standardMap.put(Integer.valueOf(61449), Integer.valueOf(113));
		this.standardMap.put(Integer.valueOf(61450), Integer.valueOf(114));
		this.standardMap.put(Integer.valueOf(61451), Integer.valueOf(115));

		this.standardMap.put(Integer.valueOf(156), Integer.valueOf(117));

		this.standardMap.put(Integer.valueOf(65480), Integer.valueOf(120));
		this.standardMap.put(Integer.valueOf(65481), Integer.valueOf(121));
		this.standardMap.put(Integer.valueOf(65483), Integer.valueOf(122));
		this.standardMap.put(Integer.valueOf(65489), Integer.valueOf(123));
		this.standardMap.put(Integer.valueOf(65485), Integer.valueOf(124));
		this.standardMap.put(Integer.valueOf(65487), Integer.valueOf(125));
		this.standardMap.put(Integer.valueOf(65488), Integer.valueOf(126));

		this.standardMap.put(Integer.valueOf(3), Integer.valueOf(155));
		this.standardMap.put(Integer.valueOf(12), Integer.valueOf(156));

		this.standardMap.put(Integer.valueOf(108), Integer.valueOf(159));
		this.standardMap.put(Integer.valueOf(226), Integer.valueOf(100));

		this.standardMap.put(Integer.valueOf(999), Integer.valueOf(135));
		this.standardMap.put(Integer.valueOf(240), Integer.valueOf(136));
		this.standardMap.put(Integer.valueOf(220), Integer.valueOf(137));
		this.standardMap.put(Integer.valueOf(28), Integer.valueOf(138));
		this.standardMap.put(Integer.valueOf(29), Integer.valueOf(139));
		this.standardMap.put(Integer.valueOf(243), Integer.valueOf(53));
		this.standardMap.put(Integer.valueOf(244), Integer.valueOf(53));
		this.standardMap.put(Integer.valueOf(242), Integer.valueOf(57));
		this.standardMap.put(Integer.valueOf(263), Integer.valueOf(53));

		this.leftMap.put(Integer.valueOf(17), Integer.valueOf(224));
		this.leftMap.put(Integer.valueOf(16), Integer.valueOf(225));
		this.leftMap.put(Integer.valueOf(18), Integer.valueOf(226));
		this.leftMap.put(Integer.valueOf(524), Integer.valueOf(227));

		this.rightMap.put(Integer.valueOf(17), Integer.valueOf(228));
		this.rightMap.put(Integer.valueOf(16), Integer.valueOf(229));
		this.rightMap.put(Integer.valueOf(18), Integer.valueOf(230));
		this.rightMap.put(Integer.valueOf(524), Integer.valueOf(231));
	}

	public void setAutoKeybreakMode(boolean paramBoolean) {
		this.autoKeybreakModeOn = paramBoolean;
	}

	public boolean getAutoKeybreakMode() {
		return this.autoKeybreakModeOn;
	}

	public byte[] convertKeyCode(int keyCode, int keyLocation, boolean keyPress, char keyChar) {
		Integer localInteger = new Integer(0);
		byte[] arrayOfByte = new byte[6];
		boolean bool = false;
		switch (keyLocation) {
		case 2:
			localInteger = (Integer) this.leftMap.get(Integer.valueOf(keyCode));
			break;
		case 4:
			localInteger = (Integer) this.keypadMap.get(Integer.valueOf(keyCode));
			break;
		case 3:
			localInteger = (Integer) this.rightMap.get(Integer.valueOf(keyCode));
			break;
		case 1:
			localInteger = (Integer) this.standardMap.get(Integer.valueOf(keyCode));
			break;
		case 0:
			System.err.println(LocaleStrings.getString("AD_1_USBKP"));
			break;
		default:
			System.err.println(LocaleStrings.getString("AD_2_USBKP"));
		}
		if (localInteger != null) {
			switch (keyCode) {
			case 17:
				if (keyLocation == 2) {
					if (keyPress) {
						modifiers = (byte) (modifiers | 0x1);
					} else {
						modifiers = (byte) (modifiers & 0xFFFFFFFE);
					}
				} else if (keyPress) {
					modifiers = (byte) (modifiers | 0x10);
				} else {
					modifiers = (byte) (modifiers & 0xFFFFFFEF);
				}
				break;

			case 16:
				if (keyLocation == 2) {
					if (keyPress) {
						modifiers = (byte) (modifiers | 0x2);
					} else {
						modifiers = (byte) (modifiers & 0xFFFFFFFD);
						modifiers = (byte) (modifiers & 0xFFFFFFDF);
					}
				} else if (keyPress) {
					modifiers = (byte) (modifiers | 0x20);
				} else {
					modifiers = (byte) (modifiers & 0xFFFFFFDF);
					modifiers = (byte) (modifiers & 0xFFFFFFFD);
				}

				break;

			case 18:
				if (keyLocation == 2) {
					if (keyPress) {
						modifiers = (byte) (modifiers | 0x4);
					} else {
						modifiers = (byte) (modifiers & 0xFFFFFFFB);
					}
				} else if (keyPress) {
					modifiers = (byte) (modifiers | 0x40);
				} else {
					modifiers = (byte) (modifiers & 0xFFFFFFBF);
				}
				break;

			case 524:
				if (keyLocation == 2) {
					if (keyPress) {
						modifiers = (byte) (modifiers | 0x8);
					} else {
						modifiers = (byte) (modifiers & 0xFFFFFFF7);
					}
				} else if (keyPress) {
					modifiers = (byte) (modifiers | 0x80);
				} else {
					modifiers = (byte) (modifiers & 0xFF7F);
				}
				break;

			default:
				if ((keyPress) || (keyCode == 154)) {
					arrayOfByte[0] = localInteger.byteValue();
					if (this.autoKeybreakModeOn) {
						bool = true;
					}
				} else if ((!this.autoKeybreakModeOn) || (keyCode == 144) || (keyCode == 20)
						|| (keyCode == 145)) {

					arrayOfByte[0] = 0;
				} else {
					return null;
				}
				break;
			}

			return USBKeyboardRepPkt(arrayOfByte, modifiers, bool);
		}
		Debug.out.println(LocaleStrings.getString("AD_3_USBKP") + KeyEvent.getKeyText(keyCode));
		return null;
	}

	public byte[] USBKeyboardRepPkt(byte[] paramArrayOfByte, byte paramByte, boolean paramBoolean) {
		ByteBuffer localByteBuffer = ByteBuffer.allocate(8);
		localByteBuffer.order(ByteOrder.LITTLE_ENDIAN);

		localByteBuffer.put(paramByte);

		localByteBuffer.put((byte) (paramBoolean ? 1 : 0));

		localByteBuffer.put(paramArrayOfByte);
		return localByteBuffer.array();
	}

	public static byte getModifiers() {
		return modifiers;
	}

	public static void setModifiers(byte paramByte) {
		modifiers = paramByte;
	}
}